package edu.hitwh.service;

import edu.hitwh.Repository.BookRepository;
import edu.hitwh.Repository.TransactionQuery;
import edu.hitwh.Repository.TransactionRepository;
import edu.hitwh.Repository.TransactionSpecifications;
import edu.hitwh.entity.Book;
import edu.hitwh.entity.BorrowTransactionStatus;
import edu.hitwh.entity.Transaction;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class TransactionService {
    private final TransactionRepository transactionRepository;
    private final BookRepository bookRepository;

    public Page<Transaction> search(TransactionQuery query, Pageable pageable) {
        return transactionRepository.findAll(TransactionSpecifications.getSpecification(query), pageable);
    }

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void create(Transaction transaction) {
        Book book = bookRepository.findById(transaction.getBook().getId())
                .orElseThrow(() -> new EntityNotFoundException("Book not found"));

        if (book.getAvailableCopies() <= 0) {
            throw new IllegalStateException("No available copies");
        }

        book.setAvailableCopies(book.getAvailableCopies() - 1);
        transaction.setStatus(BorrowTransactionStatus.BORROWED);

        bookRepository.save(book);
        transactionRepository.save(transaction);
    }

    @Transactional
    public void close(Integer transactionId) {
        Transaction transaction = transactionRepository.findById(Long.valueOf(transactionId))
                .orElseThrow(() -> new EntityNotFoundException("Transaction not found"));

        if (transaction.getStatus() != BorrowTransactionStatus.BORROWED) {
            throw new IllegalStateException("Transaction is not active");
        }

        Book book = bookRepository.findById(transaction.getBook().getId())
                .orElseThrow(() -> new EntityNotFoundException("Book not found"));

        book.setAvailableCopies(book.getAvailableCopies() + 1);
        transaction.setStatus(BorrowTransactionStatus.RETURNED);
        transaction.setReturnDate(new java.sql.Timestamp(System.currentTimeMillis()));

        bookRepository.save(book);
        transactionRepository.save(transaction);
    }
}